#include "StdAfx.h"
#include "VirtualMachine.h"

#include <iostream>
#include <string>
#include "vix.h"
#include "ConfigFile/ConfigFile.h"
#include "VixHandleGuard.h"
#include "Utils.h"

using namespace std;
using namespace System;

namespace VirtualOps { namespace Vix {

    void VirtualMachine::SetProperties()
    {
          char* vmxPath = NULL;   /** Full path to VMTeam */
          char* vmTeamPath = NULL; /** Team path, if member of the team */
          int   vmNumVCPUS;
          int	vmInVMTeam;
          int	vmIsRunning;
          /** VM Power state: On | Off | Suspended | Tools running | Resetting | Blocked on msg */
          VixPowerState	vmPowerState;
          int	vmMemorySize;
          /** VM Tools state: Unknown | Running | Not installed */
          VixToolsState	vmToolsState;
			cout<< "SetProperties" << endl;
          Vix_GetProperties(_vmHandle,
			    VIX_PROPERTY_VM_POWER_STATE,    &vmPowerState,
			    VIX_PROPERTY_VM_VMX_PATHNAME,   &vmxPath,
			    VIX_PROPERTY_VM_VMTEAM_PATHNAME,&vmTeamPath,
			    VIX_PROPERTY_VM_MEMORY_SIZE,    &vmMemorySize,
			    VIX_PROPERTY_VM_IN_VMTEAM,      &vmInVMTeam,
			    VIX_PROPERTY_VM_TOOLS_STATE,    &vmToolsState,
			    VIX_PROPERTY_VM_IS_RUNNING,     &vmIsRunning,
			    VIX_PROPERTY_VM_NUM_VCPUS,      &vmNumVCPUS,
			    VIX_PROPERTY_NONE);
          
          _path = gcnew String(vmxPath);
		  _teamPath = gcnew String(vmTeamPath);
		  _memorySize = vmMemorySize;
		  _inVMTeam = vmInVMTeam;
		  _powerState = vmPowerState;
		  _toolsState = vmToolsState;
		  _isRunning = vmIsRunning;
		  _numVCPUS = vmNumVCPUS;
		 
          //TODO: set other properties

          Vix_FreeBuffer(vmxPath);
          Vix_FreeBuffer(vmTeamPath);

          ParseVmx(); 
    }

	void VirtualMachine::Resume()
	{

	string name = Utils::MarshalString(this->_name);
	string path = Utils::MarshalString(this->_path);
	string teamPath = Utils::MarshalString(this->_teamPath);
	
	cout << endl << "Guest OS:" << name << endl;
	cout <<  "Configuration file:" << path << endl;
	cout <<  "State:" << this->_powerState << endl;
	cout <<  "TeamPath:" << teamPath << endl;
	cout <<  "Memory:" << this->_memorySize << endl;
	cout <<  "Processors:" << this->_numVCPUS << endl;
	

	}

	void VirtualMachine::Start()
	{
		VixHandleGuard jobHandle = VixVM_PowerOn(_vmHandle,
										 VIX_VMPOWEROP_LAUNCH_GUI,
										 VIX_INVALID_HANDLE,
										 NULL, // *callbackProc,
										 NULL); // *clientData);
		VixError err = VixJob_Wait(jobHandle, VIX_PROPERTY_NONE);
		if (VIX_OK != err) {
			Utils::ThrowVirtualOpsException(err);
		} else {
			cout << endl << "VM started..." << endl;
			}
		SetProperties();
	}

	void VirtualMachine::Stop()
	{
		VixHandleGuard jobHandle = VixVM_PowerOff(_vmHandle,
										 VIX_VMPOWEROP_LAUNCH_GUI,
										 NULL, // *callbackProc,
										 NULL); // *clientData);
		VixError err = VixJob_Wait(jobHandle, VIX_PROPERTY_NONE);
		if (VIX_OK != err) {
			Utils::ThrowVirtualOpsException(err);
		} else {
			cout << endl << "VM stopped..." << endl;
			}
		SetProperties();
	}

	void VirtualMachine::Suspend()
	{
		VixHandleGuard jobHandle = VixVM_Suspend(_vmHandle,
										 VIX_VMPOWEROP_NORMAL,
										 NULL, // *callbackProc,
										 NULL); // *clientData);
		VixError err = VixJob_Wait(jobHandle, VIX_PROPERTY_NONE);
		if (VIX_OK != err) {
			Utils::ThrowVirtualOpsException(err);
		} else {
			cout << endl << "VM suspended..." << endl;
			}
		SetProperties();
	}

	void VirtualMachine::Remove()
	{
		VixHandleGuard jobHandle = VixVM_Delete(_vmHandle,
										 VIX_VMPOWEROP_NORMAL,
										 NULL, // *callbackProc,
										 NULL); // *clientData);
		VixError err = VixJob_Wait(jobHandle, VIX_PROPERTY_NONE);
		if (VIX_OK != err) {
			Utils::ThrowVirtualOpsException(err);
		} else {
			cout << endl << "VM removed..." << endl;
			}
		SetProperties();
	}

    void VirtualMachine::ParseVmx()
    {
        ConfigFile config (Utils::MarshalString(_path));
        string name = config.read<string>("displayName");
        _name = gcnew String(name.c_str());
    }
} } // namespace VirtualOps::Vix
